🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / .specify / extensions / git / scripts / powershell / auto-commit.ps1
Displaying Raw • Download
.specify/extensions/git/scripts/powershell/auto-commit.ps1 bd2863243bab6eb213401d949839a2bc74dde7e2 (bd286324) Text, 5.37 KB
T8b949e#!/usr/bin/env pwsh
T8b949e# Git extension: auto-commit.ps1
T8b949e# Automatically commit changes after a Spec Kit command completes.
T8b949e# Checks per-command config keys in git-config.yml before committing.
T8b949e#
T8b949e# Usage: auto-commit.ps1 <event_name>
T8b949e# e.g.: auto-commit.ps1 after_specify
Tff7b72paramTb4b4b4(
Tb4b4b4[Tff7b72ParameterTb4b4b4(Tff7b72Position Tb4b4b4= Te6edf30Tb4b4b4, Tff7b72Mandatory Tb4b4b4= Te6edf3$trueTb4b4b4)Tb4b4b4]
Tff7b72[string]Te6edf3$EventName
Tb4b4b4)
Te6edf3$ErrorActionPreference Tb4b4b4= Ta5d6ff'Stop'
Tff7b72function Tffa657Find-ProjectRoot Tb4b4b4{
Tff7b72paramTb4b4b4(Tff7b72[string]Te6edf3$StartDirTb4b4b4)
Te6edf3$current Tb4b4b4= Tffa657Resolve-Path Te6edf3$StartDir
Tff7b72while Tb4b4b4(Te6edf3$trueTb4b4b4) Tb4b4b4{
Tff7b72foreach Tb4b4b4(Te6edf3$marker Tff7b72in Tb4b4b4@Tb4b4b4(Ta5d6ff'.specify'Tb4b4b4, Ta5d6ff'.git'Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tffa657Test-Path Tb4b4b4(Tffa657Join-Path Te6edf3$current Te6edf3$markerTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3$current
Tb4b4b4}
Tb4b4b4}
Te6edf3$parent Tb4b4b4= Tffa657Split-Path Te6edf3$current Te6edf3-Parent
Tff7b72if Tb4b4b4(Te6edf3$parent Tff7b72-eq Te6edf3$currentTb4b4b4) Tb4b4b4{ Tff7b72return Te6edf3$null Tb4b4b4}
Te6edf3$current Tb4b4b4= Te6edf3$parent
Tb4b4b4}
Tb4b4b4}
Te6edf3$repoRoot Tb4b4b4= Tffa657Find-ProjectRoot Te6edf3-StartDir Te6edf3$PSScriptRoot
Tff7b72if Tb4b4b4(Tff7b72-not Te6edf3$repoRootTb4b4b4) Tb4b4b4{ Te6edf3$repoRoot Tb4b4b4= Tffa657Get-Location Tb4b4b4}
Tffa657Set-Location Te6edf3$repoRoot
T8b949e# Check if git is available
Tff7b72if Tb4b4b4(Tff7b72-not Tb4b4b4(Tffa657Get-Command Te6edf3git Te6edf3-ErrorAction Te6edf3SilentlyContinueTb4b4b4)Tb4b4b4) Tb4b4b4{
Tffa657Write-Warning Ta5d6ff"Ta5d6ff[specify] Warning: Git not found; skipped auto-commitTa5d6ff"
Te6edf3exit Te6edf30
Tb4b4b4}
T8b949e# Temporarily relax ErrorActionPreference so git stderr warnings
T8b949e# (e.g. CRLF notices on Windows) do not become terminating errors.
Te6edf3$savedEAP Tb4b4b4= Te6edf3$ErrorActionPreference
Te6edf3$ErrorActionPreference Tb4b4b4= Ta5d6ff'Continue'
Tff7b72try Tb4b4b4{
Te6edf3git Te6edf3revTe6edf3-parse Tb4b4b4-Tff7b72-isTe6edf3-insideTe6edf3-workTe6edf3-tree Te6edf32Tb4b4b4>Te6edf3$null Tb4b4b4| Tffa657Out-Null
Te6edf3$isRepo Tb4b4b4= Te6edf3$LASTEXITCODE Tff7b72-eq Te6edf30
Tb4b4b4} Tff7b72finally Tb4b4b4{
Te6edf3$ErrorActionPreference Tb4b4b4= Te6edf3$savedEAP
Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72-not Te6edf3$isRepoTb4b4b4) Tb4b4b4{
Tffa657Write-Warning Ta5d6ff"Ta5d6ff[specify] Warning: Not a Git repository; skipped auto-commitTa5d6ff"
Te6edf3exit Te6edf30
Tb4b4b4}
T8b949e# Read per-command config from git-config.yml
Te6edf3$configFile Tb4b4b4= Tffa657Join-Path Te6edf3$repoRoot Ta5d6ff"Ta5d6ff.specify/extensions/git/git-config.ymlTa5d6ff"
Te6edf3$enabled Tb4b4b4= Te6edf3$false
Te6edf3$commitMsg Tb4b4b4= Ta5d6ff"Ta5d6ff"
Tff7b72if Tb4b4b4(Tffa657Test-Path Te6edf3$configFileTb4b4b4) Tb4b4b4{
T8b949e# Parse YAML to find auto_commit section
Te6edf3$inAutoCommit Tb4b4b4= Te6edf3$false
Te6edf3$inEvent Tb4b4b4= Te6edf3$false
Te6edf3$defaultEnabled Tb4b4b4= Te6edf3$false
Tff7b72foreach Tb4b4b4(Te6edf3$line Tff7b72in Tffa657Get-Content Te6edf3$configFileTb4b4b4) Tb4b4b4{
T8b949e# Detect auto_commit: section
Tff7b72if Tb4b4b4(Te6edf3$line Tff7b72-match Ta5d6ff'^auto_commit:'Tb4b4b4) Tb4b4b4{
Te6edf3$inAutoCommit Tb4b4b4= Te6edf3$true
Te6edf3$inEvent Tb4b4b4= Te6edf3$false
Tff7b72continue
Tb4b4b4}
T8b949e# Exit auto_commit section on next top-level key
Tff7b72if Tb4b4b4(Te6edf3$inAutoCommit Tff7b72-and Te6edf3$line Tff7b72-match Ta5d6ff'^[a-z]'Tb4b4b4) Tb4b4b4{
Tff7b72break
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3$inAutoCommitTb4b4b4) Tb4b4b4{
T8b949e# Check default key
Tff7b72if Tb4b4b4(Te6edf3$line Tff7b72-match Ta5d6ff'^\s+default:\s*(.+)$'Tb4b4b4) Tb4b4b4{
Te6edf3$val Tb4b4b4= Te6edf3$matchesTb4b4b4[Te6edf31Tb4b4b4]Tb4b4b4.Te6edf3TrimTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3ToLowerTb4b4b4(Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3$val Tff7b72-eq Ta5d6ff'true'Tb4b4b4) Tb4b4b4{ Te6edf3$defaultEnabled Tb4b4b4= Te6edf3$true Tb4b4b4}
Tb4b4b4}
T8b949e# Detect our event subsection
Tff7b72if Tb4b4b4(Te6edf3$line Tff7b72-match Ta5d6ff"Ta5d6ff^\s+Ta5d6ff$Ta5d6ff{EventName}:Ta5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3$inEvent Tb4b4b4= Te6edf3$true
Tff7b72continue
Tb4b4b4}
T8b949e# Inside our event subsection
Tff7b72if Tb4b4b4(Te6edf3$inEventTb4b4b4) Tb4b4b4{
T8b949e# Exit on next sibling key (2-space indent, not 4+)
Tff7b72if Tb4b4b4(Te6edf3$line Tff7b72-match Ta5d6ff'^\s{2}[a-z]' Tff7b72-and Te6edf3$line Tff7b72-notmatch Ta5d6ff'^\s{4}'Tb4b4b4) Tb4b4b4{
Te6edf3$inEvent Tb4b4b4= Te6edf3$false
Tff7b72continue
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3$line Tff7b72-match Ta5d6ff'\s+enabled:\s*(.+)$'Tb4b4b4) Tb4b4b4{
Te6edf3$val Tb4b4b4= Te6edf3$matchesTb4b4b4[Te6edf31Tb4b4b4]Tb4b4b4.Te6edf3TrimTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3ToLowerTb4b4b4(Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3$val Tff7b72-eq Ta5d6ff'true'Tb4b4b4) Tb4b4b4{ Te6edf3$enabled Tb4b4b4= Te6edf3$true Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3$val Tff7b72-eq Ta5d6ff'false'Tb4b4b4) Tb4b4b4{ Te6edf3$enabled Tb4b4b4= Te6edf3$false Tb4b4b4}
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3$line Tff7b72-match Ta5d6ff'\s+message:\s*(.+)$'Tb4b4b4) Tb4b4b4{
Te6edf3$commitMsg Tb4b4b4= Te6edf3$matchesTb4b4b4[Te6edf31Tb4b4b4]Tb4b4b4.Te6edf3TrimTb4b4b4(Tb4b4b4) Tff7b72-replace Ta5d6ff'^["'']' Tff7b72-replace Ta5d6ff'["'']$'
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
T8b949e# If event-specific key not found, use default
Tff7b72if Tb4b4b4(Tff7b72-not Te6edf3$enabled Tff7b72-and Te6edf3$defaultEnabledTb4b4b4) Tb4b4b4{
Te6edf3$hasEventKey Tb4b4b4= Tffa657Select-String Te6edf3-Path Te6edf3$configFile Te6edf3-Pattern Ta5d6ff"Ta5d6ff^\s*Ta5d6ff$Ta5d6ff{EventName}:Ta5d6ff" Te6edf3-Quiet
Tff7b72if Tb4b4b4(Tff7b72-not Te6edf3$hasEventKeyTb4b4b4) Tb4b4b4{
Te6edf3$enabled Tb4b4b4= Te6edf3$true
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e# No config file — auto-commit disabled by default
Te6edf3exit Te6edf30
Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72-not Te6edf3$enabledTb4b4b4) Tb4b4b4{
Te6edf3exit Te6edf30
Tb4b4b4}
T8b949e# Check if there are changes to commit
T8b949e# Relax ErrorActionPreference so CRLF warnings on stderr do not terminate.
Te6edf3$savedEAP Tb4b4b4= Te6edf3$ErrorActionPreference
Te6edf3$ErrorActionPreference Tb4b4b4= Ta5d6ff'Continue'
Tff7b72try Tb4b4b4{
Te6edf3git Tffa657diff Tb4b4b4-Te6edf3-quiet Te6edf3HEAD Te6edf32Tb4b4b4>Te6edf3$nullTb4b4b4; Te6edf3$d1 Tb4b4b4= Te6edf3$LASTEXITCODE
Te6edf3git Tffa657diff Tb4b4b4-Te6edf3-cached Tb4b4b4-Te6edf3-quiet Te6edf32Tb4b4b4>Te6edf3$nullTb4b4b4; Te6edf3$d2 Tb4b4b4= Te6edf3$LASTEXITCODE
Te6edf3$untracked Tb4b4b4= Te6edf3git Te6edf3lsTe6edf3-files Tb4b4b4-Te6edf3-others Tb4b4b4-Te6edf3-excludeTe6edf3-standard Te6edf32Tb4b4b4>Te6edf3$null
Tb4b4b4} Tff7b72finally Tb4b4b4{
Te6edf3$ErrorActionPreference Tb4b4b4= Te6edf3$savedEAP
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3$d1 Tff7b72-eq Te6edf30 Tff7b72-and Te6edf3$d2 Tff7b72-eq Te6edf30 Tff7b72-and Tff7b72-not Te6edf3$untrackedTb4b4b4) Tb4b4b4{
Tffa657Write-Host Ta5d6ff"Ta5d6ff[specify] No changes to commit after Ta5d6ff$Ta5d6ffEventNameTa5d6ff" Te6edf3-ForegroundColor Te6edf3DarkGray
Te6edf3exit Te6edf30
Tb4b4b4}
T8b949e# Derive a human-readable command name from the event
Te6edf3$commandName Tb4b4b4= Te6edf3$EventName Tff7b72-replace Ta5d6ff'^after_'Tb4b4b4, Ta5d6ff'' Tff7b72-replace Ta5d6ff'^before_'Tb4b4b4, Ta5d6ff''
Te6edf3$phase Tb4b4b4= Tff7b72if Tb4b4b4(Te6edf3$EventName Tff7b72-match Ta5d6ff'^before_'Tb4b4b4) Tb4b4b4{ Ta5d6ff'before' Tb4b4b4} Tff7b72else Tb4b4b4{ Ta5d6ff'after' Tb4b4b4}
T8b949e# Use custom message if configured, otherwise default
Tff7b72if Tb4b4b4(Tff7b72-not Te6edf3$commitMsgTb4b4b4) Tb4b4b4{
Te6edf3$commitMsg Tb4b4b4= Ta5d6ff"Ta5d6ff[Spec Kit] Auto-commit Ta5d6ff$Ta5d6ffphase Ta5d6ff$Ta5d6ffcommandNameTa5d6ff"
Tb4b4b4}
T8b949e# Stage and commit
T8b949e# Relax ErrorActionPreference so CRLF warnings on stderr do not terminate,
T8b949e# while still allowing redirected error output to be captured for diagnostics.
Te6edf3$savedEAP Tb4b4b4= Te6edf3$ErrorActionPreference
Te6edf3$ErrorActionPreference Tb4b4b4= Ta5d6ff'Continue'
Tff7b72try Tb4b4b4{
Te6edf3$out Tb4b4b4= Te6edf3git Te6edf3add Tb4b4b4. Te6edf32Tb4b4b4>Tb4b4b4&Te6edf31 Tb4b4b4| Tffa657Out-String
Tff7b72if Tb4b4b4(Te6edf3$LASTEXITCODE Tff7b72-ne Te6edf30Tb4b4b4) Tb4b4b4{ Tff7b72throw Ta5d6ff"Ta5d6ffgit add failed: Ta5d6ff$Ta5d6ffoutTa5d6ff" Tb4b4b4}
Te6edf3$out Tb4b4b4= Te6edf3git Te6edf3commit Te6edf3-q Te6edf3-m Te6edf3$commitMsg Te6edf32Tb4b4b4>Tb4b4b4&Te6edf31 Tb4b4b4| Tffa657Out-String
Tff7b72if Tb4b4b4(Te6edf3$LASTEXITCODE Tff7b72-ne Te6edf30Tb4b4b4) Tb4b4b4{ Tff7b72throw Ta5d6ff"Ta5d6ffgit commit failed: Ta5d6ff$Ta5d6ffoutTa5d6ff" Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4{
Tffa657Write-Warning Ta5d6ff"Ta5d6ff[specify] Error: Ta5d6ff$Ta5d6ff_Ta5d6ff"
Te6edf3exit Te6edf31
Tb4b4b4} Tff7b72finally Tb4b4b4{
Te6edf3$ErrorActionPreference Tb4b4b4= Te6edf3$savedEAP
Tb4b4b4}
Tffa657Write-Host Ta5d6ff"Ta5d6ff[OK] Changes committed Ta5d6ff$Ta5d6ffphase Ta5d6ff$Ta5d6ffcommandNameTa5d6ff"
Served by rngit 1.5.1 - Generated in 0.06s